package com.pro.common.modules.service.dependencies.util;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pro.framework.api.enums.EnumSortDirection;
import com.pro.framework.api.model.dto.CursorPageResult;
import com.pro.framework.api.model.dto.CursorQueryParam;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

/**
 * 游标查询工具类
 */
@Slf4j
public class CursorQueryUtil {
    
    /**
     * 执行游标查询
     */
    public static <T> List<T> executeCursorQuery(IService<T> service, CursorQueryParam param) {
        return executeCursorQuery(service, param, null);
    }
    
    /**
     * 执行带条件的游标查询
     */
    public static <T> List<T> executeCursorQuery(IService<T> service, CursorQueryParam param,
                                               Consumer<QueryWrapper<T>> condition) {
        if (service == null || param == null || !param.isValid()) {
            log.warn("游标查询参数无效: service={}, param={}", service, param);
            return Collections.emptyList();
        }
        
        try {
            QueryWrapper<T> wrapper = buildCursorWrapper(param, condition);
            return service.list(wrapper);
        } catch (Exception e) {
            log.error("游标查询执行失败: {}", e.getMessage());
            return Collections.emptyList();
        }
    }
    
    /**
     * 执行游标分页查询
     */
    public static <T> CursorPageResult<T> executeCursorPageQuery(IService<T> service,
                                                                 CursorQueryParam param) {
        return executeCursorPageQuery(service, param, null);
    }
    
    public static <T> CursorPageResult<T> executeCursorPageQuery(IService<T> service, 
                                                               CursorQueryParam param,
                                                               Consumer<QueryWrapper<T>> condition) {
        List<T> data = executeCursorQuery(service, param, condition);
        Long nextCursor = extractLastCursor(data, param.getOrderBy());
        
        return new CursorPageResult<>(data, nextCursor, param.getLimit());
    }
    
    /**
     * 构建游标查询包装器
     */
    private static <T> QueryWrapper<T> buildCursorWrapper(CursorQueryParam param, 
                                                        Consumer<QueryWrapper<T>> condition) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        
        // 游标条件
        if (param.getCursor() != null) {
            String orderField = getOrderField(param);
            if (param.getDirection() == EnumSortDirection.DESC) {
                wrapper.lt(orderField, param.getCursor());
            } else {
                wrapper.gt(orderField, param.getCursor());
            }
        }
        
        // 额外条件
        if (condition != null) {
            condition.accept(wrapper);
        }
        
        // 排序和分页
        String orderField = getOrderField(param);
        boolean isAsc = param.getDirection() != EnumSortDirection.DESC;
        wrapper.orderBy(true, isAsc, orderField)
               .last("LIMIT " + param.getLimit());
        
        return wrapper;
    }
    
    private static String getOrderField(CursorQueryParam param) {
        return param.getOrderBy() != null ? param.getOrderBy() : "id";
    }
    
    /**
     * 提取最后一个游标值
     */
    private static <T> Long extractLastCursor(List<T> data, String cursorField) {
        if (data == null || data.isEmpty()) {
            return null;
        }
        
        T lastItem = data.get(data.size() - 1);
        try {
            String fieldName = cursorField != null ? cursorField : "id";
            Field field = lastItem.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            Object value = field.get(lastItem);
            return ((Number) value).longValue();
        } catch (Exception e) {
            log.warn("提取游标值失败, 使用默认id字段", e);
            return null;
        }
    }
}